﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SdmxMl.Common;
using SdmxMl.Structure;
using SdmxMl.Manager;

namespace SdmxMl.Helper
{
    public class HierarchicalCloner
    {
        public SmManager Cache { get { return this.sm; } }

        private SmManager sm;

        public HierarchicalCloner(SmManager smMgr)
        {
            sm = smMgr == null ? ReferenceManager.GetSmContainerImage() : smMgr;
        }

        public HierarchicalCodelistType Clone(ArtefactRefBase reference, string clonedVersion)
        {
            HierarchicalCodelistType hclSource = this.sm.GetArtefact(SdmxArtefactType.HierarchicalCodelists, reference, true) as HierarchicalCodelistType;
            if (hclSource == null)
                throw new ApplicationException("Unable to obtain hierarchical codelist: " + reference.ToString());
            // Clone source 
            HierarchicalCodelistType hclCloned = CloneArtefact(this.sm, new ArtefactRefTyped(SdmxArtefactType.HierarchicalCodelists, hclSource.FullIdent), clonedVersion) as HierarchicalCodelistType;

            // Now we clone each codelist and update references to codelists
            foreach (CodelistRefType clrt in hclCloned.CodelistRefList)
            {
                CloneArtefact(this.sm, new ArtefactRefTyped(SdmxArtefactType.CodeLists, clrt.FullIdent), clonedVersion);
                clrt.Version = clonedVersion;
            }

            return hclCloned;
       }

        private Artefact CloneArtefact(SmManager sm, ArtefactRefTyped reference, string clonedVersion)
        {
            Artefact arSource = sm.GetArtefact(reference.Type, reference, true);
            if (arSource == null)
                throw new ApplicationException("Unable to obtain metadata: " + reference.ToString());
            // Clone source 
            string sourceVersion = arSource.Version;
            arSource.Version = clonedVersion;
            ArtefactManager am = sm.GetArtefactManager(reference.Type);
            string tempf = am.SaveTempArtefact(arSource);
            arSource.Version = sourceVersion;
            if (string.IsNullOrEmpty(tempf))
                throw new ApplicationException("Unable to persist artefact: " + reference.ToString());
            sm.LoadSdmxDocument(tempf, true, null);
            ArtefactRefBase clonedReference = new ArtefactRefBase(arSource.Id, arSource.AgencyId, clonedVersion);
            Artefact arCloned = sm.GetArtefact(reference.Type, clonedReference);
            if (arCloned == null)
                throw new ApplicationException("Unable to obtain clone artefact: " + clonedReference.ToString());

            return arCloned;
        }
    }
}
